#ifndef LCCTOOLBOX_MESS

#include<functional>
#include"lcctoolbox_block.hpp"
#include"lcctoolbox_markset.hpp"
#include"ext_type_traits.hpp"

namespace LccToolbox{


typedef std::function<char*(char*,char*)> unifunc;

template<class T> T* ptras(void*p){	return reinterpret_cast<T*>(p);}




// type part

struct TypeOutline{
	size_t type;
	size_t size;
	GmarkSetAuto<size_t> member;// pag record offset
	GmarkSetAuto<unifunc> func;// pag record funcObj
	// void print()
};


typedef GmarkSetAuto<TypeOutline> TYPES;








// var part

struct VAR:public Block{
	size_t& type(){return *(this->ptras<size_t>());}
	char* data(){return ptr(sizeof(size_t));}
	// char* data(note)// get member
	// void print()
};


class VARS:public GmarkSetAuto<VAR>{
	friend class VARX;
	TYPES* types_p=nullptr;
	mark typeCall;

public:
	template<class T> bool form(T&& call);
};


class VARX:public GmarkSet<VARS>{
	friend class MESS;
	TYPES* types_p=nullptr;
	
public:
	void link(TYPES& types){ types_p=&types;}
	template<class T> bool form(T&& type);
};








// mix part

/**
 * MESS mess// link types with varx
 * 
 * mess.define(note,arg...)// types&varx form
 * mess.surround(note)// for easy coding, multi-thread aware
 * mess.appendMark(note,pos,typeID);// member
 * mess.appendFunc(note,function);
 * mess.instantiate(note);
 * 
 * mess.undefine(note)// the data will also be removed or ...
 * mess.print(note)// type then outline(include func), obj then key-value
 * */
class MESS{
	TYPES types;
	VARX varx;
	smark bindType;
	bool binded=false;

public:
	MESS(){varx.link(types);}

	template<class T> int define(T&&,size_t);// typeCall|typeSize
	template<class T> bool surround(T&&);
	// template<class T,class Tsub> bool appendMark(T&&,size_t offset,Tsub&&);
	template<class T> bool appendFunc(T&&,unifunc);
	template<class T> bool instantiate(T&&);
	template<class T> char* var_address(T&&);
	template<class Tfunc,class Tinstance> char* call(Tfunc&&,Tinstance&&,char* =nullptr);

	// print(note);
};








typedef std::function<void(char*)> FLOW;
class FLOWGROUP:public block<FLOW>{
public:
	void run(char* target=nullptr)
	{	for(size_t i=0;i<size();++i)
			if(operator[](i)) operator[](i)(target);
	}

	FLOWGROUP& operator=(const FLOWGROUP& src){
		block::operator=(src);
		return *this;
	}
	FLOWGROUP& operator=(FLOWGROUP&& src){
		block::operator=(std::move(src));
		return *this;
	}
};
class FLOWGROUPS:public GmarkSetAuto<FLOWGROUP>{
public:
	template<class T>
	void run( T&& note, char* target=nullptr){
		auto it=find(std::forward<T>(note));
		if(it!=end()) it->Pag.run(target);
	}

	FLOWGROUPS& operator=(const FLOWGROUPS& src){
		GmarkSetAuto<FLOWGROUP>::operator=(src);
		return *this;
	}
	FLOWGROUPS& operator=(FLOWGROUPS&& src){
		GmarkSetAuto<FLOWGROUP>::operator=(std::move(src));
		return *this;
	}
};


}// namespace LccToolbox

#include"inl/lcctoolbox_mess.inl"
#define LCCTOOLBOX_MESS
#endif